package com.wxy.school.controller;

import cn.hutool.json.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wxy.school.common.Constant;
import com.wxy.school.common.R;
import com.wxy.school.config.AlipayConfig;
import com.wxy.school.entity.Alipay;
import com.wxy.school.entity.Orders;
import com.wxy.school.service.OrdersService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.jetbrains.annotations.NotNull;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 王祥宇
 * @projectName school
 * @packageName com.wxy.school.controller
 * @data 2023/4/10 10:28
 * @description: 支付宝沙箱支付接口Controller管理层
 * @version: 1.0
 */
@RestController
@RequestMapping("school/aliPay")
public class AlipayController {

    @Resource
    private AlipayConfig alipayConfig;

    @Resource
    private OrdersService ordersService;

    /**
     * @description: 调用支付宝接口打开支付页面
     * @author: 王祥宇
     * @param: alipay
     * @param: httpServletResponse
     */
    @GetMapping("/payConfirm")
    public void payConfirm(Alipay alipay, HttpServletResponse httpServletResponse) throws Exception {

        // 支付宝沙箱买家账号 dkfwmi9488@sandbox.com
        // 支付宝沙箱买家登陆密码和支付密码 111111
        // 创建Client，通用SDK提供的Client，负责调用支付宝的API
        AlipayClient alipayClient = new DefaultAlipayClient(Constant.GATEWAY_URL,
                alipayConfig.getAppId(), alipayConfig.getAppPrivateKey(),
                Constant.FORMAT, Constant.CHARSET,
                alipayConfig.getAlipayPublicKey(), Constant.SIGN_TYPE);

        // 创建 Request并设置Request参数
        AlipayTradePagePayRequest request = getAlipayTradePagePayRequest(alipay);
        String form = "";
        try{
            // 调用支付宝sdk接口生成支付页面的表单
            form = alipayClient.pageExecute(request).getBody();
        }catch (AlipayApiException e){
            e.printStackTrace();
        }
        // 将表单信息转化为html格式并写入到页面中
        httpServletResponse.setContentType("text/html;charset=" + Constant.CHARSET);
        httpServletResponse.getWriter().write(form);
        httpServletResponse.getWriter().flush();
        httpServletResponse.getWriter().close();
    }

    private @NotNull AlipayTradePagePayRequest getAlipayTradePagePayRequest(Alipay alipay) {
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest(); // 用于发送请求的request类
        request.setNotifyUrl(alipayConfig.getNotifyUrl()); // 设置支付宝支付成功的回调方法
        request.setReturnUrl(alipayConfig.getReturnUrl()); // 设置支付宝支付成功后的回调url
        JSONObject bizContent = new JSONObject();
        bizContent.set("out_trade_no", alipay.getTraceNo()); // 设置自己根据时间戳生成的订单编号
        bizContent.set("total_amount", alipay.getTotalAmount()); // 设置支付的总金额
        bizContent.set("subject", alipay.getSubject()); // 设置支付的项目名称
        bizContent.set("product_code", "FAST_INSTANT_TRADE_PAY"); // 设置支付方式 这里设置为了网页二维码/当面付
        request.setBizContent(bizContent.toString());
        return request;
    }

    /**
     * @description: 支付成功后的回调接口
     * @author: 王祥宇
     * @param: request
     * @return: java.lang.String
     */
    @PostMapping("/notify") // 回调接口必须为POST接口
    public String payNotify(HttpServletRequest request) throws Exception {
        // 判断返回的支付状态吗是否为支付成功的状态
        if (request.getParameter("trade_status").equals("TRADE_SUCCESS")) {

            // 将返回的信息使用map存储起来
            Map<String, String> params = new HashMap<>();
            Map<String, String[]> requestParams = request.getParameterMap();
            for (String name : requestParams.keySet()) {
                params.put(name, request.getParameter(name));
            }

            String tradeNo = params.get("out_trade_no"); // 商户订单号即我们自己提交的订单编号
            String gmtPayment = params.get("gmt_payment"); // 买家的付款时间
            String alipayTradeNo = params.get("trade_no"); // 支付宝给我们返回的唯一的交易流水号
            String sign = params.get("sign"); // 获取加签方式
            String content = AlipaySignature.getSignCheckContentV1(params);
            boolean checkSignature = AlipaySignature.rsa256CheckContent(content, sign, alipayConfig.getAlipayPublicKey(), "UTF-8"); // 验证签名
            // 支付宝验签
            if (checkSignature) {
                // 更新订单未已支付
                if (params.get("trade_status").equals("TRADE_SUCCESS")) {
                    DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                    LocalDateTime localTime = LocalDateTime.parse(gmtPayment,df);
                    LambdaQueryWrapper<Orders> lambdaQueryWrapper = new LambdaQueryWrapper<>();
                    lambdaQueryWrapper.eq(Orders::getOrderId, tradeNo);
                    Orders orders = ordersService.getOne(lambdaQueryWrapper);
                    orders.setPayTime(localTime);
                    orders.setAliPayId(alipayTradeNo);
                    orders.setOrderStatus(1);
                    ordersService.updateById(orders);
                }
            }
        }
        return "success";
    }

    /**
     * @description: 支付宝退款的交易接口
     * @author: 王祥宇
     * @param: aliPay
     * @return: com.wxy.school.common.R<java.lang.String>
     */
    @GetMapping("/refund")
    public R<String> refund(Alipay aliPay) throws AlipayApiException {

        // 1. 创建Client，通用SDK提供的Client，负责调用支付宝的API
        AlipayTradeRefundResponse response = getAlipayTradeRefundResponse(aliPay);
        if (response.isSuccess()) {  // 退款成功，isSuccess 为true
            System.out.println("调用成功");

            // 4. 更新数据库状态
            LambdaQueryWrapper<Orders> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(Orders::getAliPayId, aliPay.getAlipayTraceNo());
            Orders orders = ordersService.getOne(lambdaQueryWrapper);
            orders.setOrderStatus(5);
            orders.setRefundTime(LocalDateTime.now());
            ordersService.updateById(orders);
            return R.success("退款成功");
        } else {   // 退款失败，isSuccess 为false
            System.out.println(response.getBody());
            return R.error("退款失败");
        }

    }

    private AlipayTradeRefundResponse getAlipayTradeRefundResponse(Alipay aliPay) throws AlipayApiException {
        AlipayClient alipayClient = new DefaultAlipayClient(Constant.GATEWAY_URL,
                alipayConfig.getAppId(), alipayConfig.getAppPrivateKey(),
                Constant.FORMAT, Constant.CHARSET,
                alipayConfig.getAlipayPublicKey(), Constant.SIGN_TYPE);
        // 2. 创建 Request，设置参数
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        JSONObject bizContent = new JSONObject();
        bizContent.set("trade_no", aliPay.getAlipayTraceNo());  // 支付宝回调的订单流水号
        bizContent.set("refund_amount", aliPay.getTotalAmount());  // 订单的总金额
        bizContent.set("out_request_no", aliPay.getTraceNo());   //  我的订单编号

        // 返回参数选项，按需传入
        /*
         JSONArray queryOptions = new JSONArray();
         queryOptions.add("refund_detail_item_list");
         bizContent.put("query_options", queryOptions);
         */

        request.setBizContent(bizContent.toString());

        // 3. 执行请求
        return alipayClient.execute(request);
    }
}
